-- Copyright (c) 2010, Pavel Kovar
-- All rights reserved.

---------------------------------------------------------------------------------------
-- This file is a part of the Witch Navigator project

-- PCIeIIP top level
-- Implemented  
--   * Building blocks interconnection
--   * Interrupt and DMA handling

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity PCIeIIP is
	PORT(
-- UCor IP interface
		-- External memory interface
      mem_wr_we : OUT std_logic_vector(3 downto 0);
		mem_wr_data : OUT std_logic_vector(31 downto 0);
		mem_wr_addr: OUT std_logic_vector(19 downto 0);
		mem_rd_ce : OUT std_logic;
		mem_rd_addr: OUT std_logic_vector(19 downto 0);
		mem_rd_data : IN std_logic_vector(31 downto 0);
		mem_clk : OUT std_logic;
		-- TIC signal
		dma_start : IN std_logic;
		dma_addr : IN std_logic_vector(31 downto 0);		
		int_dma_enable : IN std_logic;
-- PCI controller interface
		-- Common transaction interface signals
  		trn_clk : IN std_logic;
		trn_reset_n : IN std_logic;
		trn_lnk_up_n : IN std_logic;
		trn_fc_cplh : IN std_logic_vector(7 downto 0);
		trn_fc_cpld : IN std_logic_vector(11 downto 0);
		trn_fc_nph : IN std_logic_vector(7 downto 0);
		trn_fc_npd : IN std_logic_vector(11 downto 0);
		trn_fc_ph : IN std_logic_vector(7 downto 0);
		trn_fc_pd : IN std_logic_vector(11 downto 0);
		trn_fc_sel : OUT std_logic_vector(2 downto 0);

		-- Tx interface signals
  		trn_tbuf_av : IN std_logic_vector(5 downto 0);
		trn_tcfg_req_n : IN std_logic;
		trn_terr_drop_n : IN std_logic;
		trn_tdst_rdy_n : IN std_logic;
		trn_td : OUT std_logic_vector(31 downto 0);
		trn_tsof_n : OUT std_logic;
		trn_teof_n : OUT std_logic;		
		trn_tsrc_rdy_n : OUT std_logic;
		trn_tsrc_dsc_n : OUT std_logic;
		trn_terrfwd_n : OUT std_logic;
		trn_tstr_n : OUT std_logic;
		trn_tcfg_gnt_n : OUT std_logic;
		-- Rx interface signals
		trn_rd : IN std_logic_vector(31 downto 0);
		trn_rsof_n : IN std_logic;
		trn_reof_n : IN std_logic;
		trn_rsrc_rdy_n : IN std_logic;
		trn_rsrc_dsc_n : IN std_logic;
		trn_rerrfwd_n : IN std_logic;
		trn_rbar_hit_n : IN std_logic_vector(6 downto 0);
		trn_rdst_rdy_n : OUT std_logic;
		trn_rnp_ok_n : OUT std_logic;
		
		-- Configuration interface signals
		cfg_do : IN std_logic_vector(31 downto 0);
		cfg_rd_wr_done_n : IN std_logic;
		cfg_dwaddr : OUT std_logic_vector(9 downto 0);
		cfg_rd_en_n : OUT std_logic;
		cfg_err_ur_n : OUT std_logic;
		cfg_err_cor_n : OUT std_logic;
		cfg_err_ecrc_n : OUT std_logic;
		cfg_err_cpl_timeout_n : OUT std_logic;
		cfg_err_cpl_abort_n : OUT std_logic;
		cfg_err_posted_n : OUT std_logic;
		cfg_err_locked_n : OUT std_logic;
		cfg_err_tlp_cpl_header : OUT std_logic_vector(47 downto 0);
		cfg_err_cpl_rdy_n : IN std_logic;
		cfg_interrupt_rdy_n : IN std_logic;
		cfg_interrupt_n : OUT std_logic;
		cfg_interrupt_assert_n : out std_logic;
		cfg_interrupt_di : out std_logic_vector(7 downto 0);
		cfg_interrupt_do : in std_logic_vector(7 downto 0);
		cfg_interrupt_mmenable : in std_logic_vector(2 downto 0);
		cfg_interrupt_msienable : IN std_logic;
		cfg_to_turnoff_n : in std_logic;
		cfg_turnoff_ok_n : out std_logic;
		cfg_bus_number : IN std_logic_vector(7 downto 0);
		cfg_function_number : IN std_logic_vector(2 downto 0);
		cfg_status : IN std_logic_vector(15 downto 0);
		cfg_command : IN std_logic_vector(15 downto 0);
		cfg_dstatus : IN std_logic_vector(15 downto 0);
		cfg_dcommand : IN std_logic_vector(15 downto 0);
		cfg_lstatus : IN std_logic_vector(15 downto 0);
		cfg_lcommand : IN std_logic_vector(15 downto 0);
		cfg_pm_wake_n : out std_logic;
		cfg_pcie_link_state_n : IN std_logic_vector(2 downto 0);
		cfg_trn_pending_n : OUT std_logic;
		cfg_dsn : out std_logic_vector(63 downto 0);
		cfg_device_number : IN std_logic_vector(4 downto 0)
		
		);
end PCIeIIP;

architecture Behavioral of PCIeIIP is

	COMPONENT PCIeCTRL
	PORT(
		clk : IN std_logic;
		rst_n : IN std_logic;
		req_compl_i : IN std_logic;
		dma_run : IN std_logic;
		compl_done_i : IN std_logic;
		cfg_to_turnoff_n : IN std_logic;          
		cfg_turnoff_ok_n : OUT std_logic
		);
	END COMPONENT;

	COMPONENT PCIeTX
	PORT(
		clk : IN std_logic;
		rst_n : IN std_logic;
		trn_tdst_rdy_n : IN std_logic;
		trn_tdst_dsc_n : IN std_logic;
		req_compl_i : IN std_logic;
		req_tc_i : IN std_logic_vector(2 downto 0);
		req_td_i : IN std_logic;
		req_ep_i : IN std_logic;
		req_attr_i : IN std_logic_vector(1 downto 0);
		req_len_i : IN std_logic_vector(9 downto 0);
		req_rid_i : IN std_logic_vector(15 downto 0);
		req_tag_i : IN std_logic_vector(7 downto 0);
		req_be_i : IN std_logic_vector(7 downto 0);
		req_addr_i : IN std_logic_vector(19 downto 0);
		rd_data_i : IN std_logic_vector(31 downto 0);
		completer_id_i : IN std_logic_vector(15 downto 0);
		cfg_bus_mstr_enable_i : IN std_logic;
		cfg_extended_tag_i : IN std_logic;
		req_dma_w_i : IN std_logic;
		dma_pc_addr_i : IN std_logic_vector(31 downto 0);
		trn_td : OUT std_logic_vector(31 downto 0);
		trn_tsof_n : OUT std_logic;
		trn_teof_n : OUT std_logic;
		trn_tsrc_rdy_n : OUT std_logic;
		trn_tsrc_dsc_n : OUT std_logic;
		compl_done_o : OUT std_logic;
		rd_addr_o : OUT std_logic_vector(19 downto 0);
		rd_mem_ce_o : OUT std_logic;
		dma_done_o : OUT std_logic
		);
	END COMPONENT;
	
	COMPONENT PCIeRX
	PORT(
		clk : IN std_logic;
		rst_n : IN std_logic;
		trn_rd : IN std_logic_vector(31 downto 0);
		trn_rsof_n : IN std_logic;
		trn_reof_n : IN std_logic;
		trn_rsrc_rdy_n : IN std_logic;
		trn_rsrc_dsc_n : IN std_logic;
		trn_rbar_hit_n : IN std_logic_vector(6 downto 0);
		compl_done_i : IN std_logic;
		completer_id_i : IN std_logic_vector(15 downto 0);          
		trn_rdst_rdy_n : OUT std_logic;
		req_compl_o : OUT std_logic;
		req_tc_o : OUT std_logic_vector(2 downto 0);
		req_td_o : OUT std_logic;
		req_ep_o : OUT std_logic;
		req_attr_o : OUT std_logic_vector(1 downto 0);
		req_len_o : OUT std_logic_vector(9 downto 0);
		req_rid_o : OUT std_logic_vector(15 downto 0);
		req_tag_o : OUT std_logic_vector(7 downto 0);
		req_be_o : OUT std_logic_vector(7 downto 0);
		req_addr_o : OUT std_logic_vector(19 downto 0);
		wr_addr_o : OUT std_logic_vector(19 downto 0);
		wr_data_o : OUT std_logic_vector(31 downto 0);
		wr_en_o : OUT std_logic_vector(3 downto 0)
		);
	END COMPONENT;


    signal req_compl : std_logic;   -- After receiving MRd32/64, set it to 1
    signal compl_done: std_logic;
    signal cfg_int_n_reg : std_logic;
    signal dma_done_o : std_logic;
    signal req_len : std_logic_vector(9 downto 0);
    signal req_tc : std_logic_vector(2 downto 0);
    signal req_td : std_logic;
    signal req_ep : std_logic;
    signal req_attr : std_logic_vector(1 downto 0);
    signal req_rid : std_logic_vector(15 downto 0);
    signal req_tag : std_logic_vector(7 downto 0);
    signal req_be : std_logic_vector(7 downto 0);
    signal req_addr : std_logic_vector(19 downto 0);
    signal dma_start_r : std_logic;
    signal dma_start_d1 : std_logic;
    signal dma_start_d2 : std_logic;
    signal completer_id : std_logic_vector(15 downto 0);

begin
    -- Common transaction interface signals
    trn_fc_sel <= "000";
    -- Tx interface signals
    trn_terrfwd_n <= '1';
    trn_tcfg_gnt_n <= '0';
    trn_tstr_n <= '1';
    -- Rx interface signals
    trn_rnp_ok_n <= '0';
    -- Configuration interface signals
    cfg_dwaddr <= "0000000000";
    cfg_rd_en_n <= '1';
    cfg_interrupt_assert_n <= '0';
    cfg_interrupt_di <= "00000000";	
    cfg_pm_wake_n <= '1';
    cfg_trn_pending_n <= '1';
    cfg_err_cor_n <= '1';
    cfg_err_ur_n <= '1';
    cfg_err_ecrc_n <= '1';
    cfg_err_cpl_timeout_n <= '1';
    cfg_err_tlp_cpl_header <= "000000000000000000000000000000000000000000000000";	
    cfg_err_cpl_abort_n <= '1';
    cfg_err_posted_n <= '0';
    cfg_err_locked_n <= '1';
    cfg_dsn <= "0000000000000000000000000000000000000000000000000000000000000000";

    completer_id(15 downto 8) <= cfg_bus_number;
    completer_id(7 downto 3) <= cfg_device_number;
    completer_id(2 downto 0) <= cfg_function_number;

    PCIeCTRL1: PCIeCTRL PORT MAP(
                                    clk => trn_clk,
                                    rst_n => trn_reset_n,
                                    req_compl_i => req_compl,
                                    dma_run => int_dma_enable,
                                    compl_done_i => compl_done,
                                    cfg_to_turnoff_n => cfg_to_turnoff_n,
                                    cfg_turnoff_ok_n => cfg_turnoff_ok_n
                                );

    PCIeTX1: PCIeTX PORT MAP(
                                clk => trn_clk,
                                rst_n => trn_reset_n,
                                trn_td => trn_td,
                                trn_tsof_n => trn_tsof_n,
                                trn_teof_n => trn_teof_n,
                                trn_tsrc_rdy_n => trn_tsrc_rdy_n,
                                trn_tsrc_dsc_n => trn_tsrc_dsc_n,
                                trn_tdst_rdy_n => trn_tdst_rdy_n,
                                trn_tdst_dsc_n => '1',
                                req_compl_i => req_compl,
                                compl_done_o => compl_done,
                                req_tc_i => req_tc,
                                req_td_i => req_td,
                                req_ep_i => req_ep,
                                req_attr_i => req_attr,
                                req_len_i => req_len,
                                req_rid_i => req_rid,
                                req_tag_i => req_tag,
                                req_be_i => req_be,
                                req_addr_i => req_addr,
                                rd_addr_o => mem_rd_addr,
                                rd_mem_ce_o => mem_rd_ce,
                                rd_data_i => mem_rd_data,
                                completer_id_i => completer_id,
                                cfg_bus_mstr_enable_i => cfg_command(2),
                                cfg_extended_tag_i => cfg_dcommand(8),
                                req_dma_w_i => dma_start_r,
                                dma_pc_addr_i => dma_addr,
                                dma_done_o => dma_done_o
                            );

    PCIeRX1: PCIeRX PORT MAP(
                                clk => trn_clk,
                                rst_n => trn_reset_n,
                                trn_rd => trn_rd,
                                trn_rsof_n => trn_rsof_n,
                                trn_reof_n => trn_reof_n,
                                trn_rsrc_rdy_n => trn_rsrc_rdy_n,
                                trn_rsrc_dsc_n => trn_rsrc_dsc_n,
                                trn_rbar_hit_n => trn_rbar_hit_n,
                                trn_rdst_rdy_n => trn_rdst_rdy_n,
                                req_compl_o => req_compl,
                                compl_done_i => compl_done,
                                req_tc_o => req_tc,
                                req_td_o => req_td,
                                req_ep_o => req_ep,
                                req_attr_o => req_attr,
                                req_len_o => req_len,
                                req_rid_o => req_rid,
                                req_tag_o => req_tag,
                                req_be_o => req_be,
                                req_addr_o => req_addr,
                                completer_id_i => completer_id,
                                wr_addr_o => mem_wr_addr,
                                wr_data_o => mem_wr_data,
                                wr_en_o => mem_wr_we		 
                            );

-- Memory interface signals
mem_clk <= trn_clk;

-- Interrupt handling
-- Interrupt is generated on the end of DMA transaction
    cfg_interrupt_n <= cfg_int_n_reg;
    process(trn_clk)
    begin
        if trn_clk'event and trn_clk = '1' then
            if (dma_done_o = '1' and int_dma_enable = '1') then
                cfg_int_n_reg <= '0';
            elsif (cfg_interrupt_rdy_n = '0' or trn_reset_n = '0') then
                cfg_int_n_reg <= '1';
            end if;			
        end if;
    end process;

-- DMA initiation signal 
    process (trn_clk)
    begin
        if trn_clk'event and trn_clk = '1' then
            dma_start_d1 <= dma_start;
            dma_start_d2 <= dma_start_d1;
            dma_start_r <= (dma_start_d1 and (not dma_start_d2) and int_dma_enable);
        end if;
    end process;

end Behavioral;

